#pragma once
#include <unordered_map>
#include <string>
#include <vector>
#include <cassert>
#include <fstream>
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include"./include/mysql.h"

namespace ns_model
{
    using namespace ns_log;
    using namespace ns_util;
    struct Question //题目的总信息
    {
        std::string number; //题目编号
        std::string title;  //题目题号
        std::string star;   //题目难度
        std::string desc;   //题目的描述信息
        std::string header; //编辑的预设代码
        std::string tail;   //测试用例，需要和header拼接形成完整代码交给后端编译
        int cpu_limit;      //题目时间限制
        int memory_limit;   //题目空间限制
    };

    const std::string oj_questions = "oj_questions"; //数据库oj的表名
    const std::string host = "127.0.0.1";
    const std::string user = "oj_client";
    const std::string passwd = "xjh+1$F.SAfds+@zh_123ds";
    const std::string db = "oj";
    const int port = 3306;

    class Model
    {
    public:
        Model() {}
        ~Model() {}

        bool QueryMysql(const std::string& sql, std::vector<Question>* out)
        {
            //1. 创建mysql句柄
            MYSQL * my = mysql_init(nullptr);
            //2. 连接数据库
            if(nullptr == mysql_real_connect(my,host.c_str(),user.c_str(),\
                                            passwd.c_str(),db.c_str(),port,nullptr,0))
            {
                LOG(FATA)<<"连接数据库失败...."<<std::endl;
                return false;
            }
            LOG(INFO)<<"连接数据成功..."<<std::endl;

            //设置编码格式
           mysql_set_character_set(my,"utf8");
            //3. 执行sql语句
            if(0 != mysql_query(my,sql.c_str()))
                LOG(WARNING)<<sql<< "execute falied"<<std::endl;
            
            //4.分析解析执行结果

            //4.1 提取结果
            MYSQL_RES *res = mysql_store_result(my);
            //4.2 解析结果
            int rows = mysql_num_rows(res); //表的行数
            int cols = mysql_num_fields(res); //表的列数

            for(int i = 0;i < rows;i++)
            {
                MYSQL_ROW row= mysql_fetch_row(res); //一行记录(MYSQL_ROW -->char** )
                Question q; //保存一行记录的题目信息
                q.number = row[0];
                q.title = row[1];
                q.star = row[2];
                q.desc  = row[3];
                q.header = row[4];
                q.tail = row[5];
                q.cpu_limit = atoi(row[6]);
                q.memory_limit = atoi(row[7]);

                out->push_back(q);
            }
            //4.3释放结果空间
            free(res);
            //5. 关闭mysql连接
            mysql_close(my);
            return true;
        }
        bool GetAllQuestions(std::vector<Question> *out)
        {
            std::string sql = "select * from ";
            sql+=oj_questions;

            return QueryMysql(sql,out);
        }
        //根据题目编号获取题目信息
        bool GetOneQuestion(const std::string &number, Question *q)
        {
            std::string sql = "select * from ";
            sql+=oj_questions;
            sql +=" where number=";
            sql+=number;

            std::vector<Question> result;
            if(QueryMysql(sql,&result))
            {
                if(result.size() == 1)
                {
                    *q = result[0];
                    return true;
                }
            }
            return false;
        }
    };
}
